﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using XmlStudio.DataLayer;
using XmlStudio.Enums;
using System.Windows;

namespace XmlStudio.ViewModel.Node {
    [DebuggerDisplay("Name: {Name}")] //"Name: {Name}, IsModified: {IsModified}, State: {State}"
    public class XmlElementViewModel : XmlNodeViewModel, INotifyPropertyChanged {
        #region Fields
        string prefix;
        string localName;
        string namespaceUri;
        readonly IList<XmlNodeViewModel> children = new List<XmlNodeViewModel>();
        ExpandState state = ExpandState.Collapsed;
        XmlAttributeCollectionViewModel attributes = new XmlAttributeCollectionViewModel();
        bool isModified;
        #endregion

        public override string ToString() {
            return string.Format("Name: {0}", Name);
        }

        #region Properties
        public bool IsModified {
            get { return this.isModified; }
            set {
                this.isModified = value;
                OnPropertyChanged("IsModified");
            }
        }

        public string Prefix {
            get { return this.prefix; }
            set {
                if(value != this.prefix) {
                    this.prefix = value;
                    this.IsModified = true;
                    OnPropertyChanged("Prefix");
                    OnPropertyChanged("Name");
                }
            }
        }

        public string LocalName {
            get { return this.localName; }
            set {
                if(value != this.localName) {
                    this.localName = value;
                    this.IsModified = true;
                    OnPropertyChanged("LocalName");
                    OnPropertyChanged("Name");
                }
            }
        }

        public string Name {
            get {
                return string.IsNullOrEmpty(this.prefix) ? this.localName : string.Format("{0}:{1}", this.prefix, this.localName);
            }
        }

        public string NamespaceURI {
            get { return this.namespaceUri; }
            set {
                if(value != this.namespaceUri) {
                    this.namespaceUri = value;
                    this.IsModified = true;
                    OnPropertyChanged("NamespaceURI");
                }
            }
        }

        public IList<XmlNodeViewModel> Children {
            get { return this.children; }
        }

        public ExpandState State {
            get { return this.state; }
            set {
                this.state = value;
                OnPropertyChanged("State");
            }
        }

        public XmlAttributeCollectionViewModel Attributes {
            get { return this.attributes; }
            set {
                this.attributes = value;
                OnPropertyChanged("Attributes");
            }
        }
        #endregion

        #region Events
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Constructors
        public XmlElementViewModel(BigXmlNode node, IInputElement commandTarget)
            : base(Guid.NewGuid().ToString(), node, commandTarget) {
            //Contract.Requires<ArgumentNullException>(param != null, "param");
            if(node == null) {
                throw new ArgumentNullException("param");
            }

            BindElement();
            BindAttributes();
            this.Attributes.CollectionChanged += Attributes_CollectionChanged;
            this.IsModified = false;
        }

        void Attributes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
            this.IsModified = true;
        }
        #endregion

        #region Event handlers
        protected void OnPropertyChanged(string propertyName) {
            if(this.PropertyChanged != null) {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region Methods
        public override void Refresh() {
            this.BindElement();
            this.BindAttributes();
            this.IsModified = false;
        }

        public void BindElement() {
            this.LocalName = this.Node.LocalName;
            this.Prefix = this.Node.Prefix;
            this.NamespaceURI = this.Node.NamespaceURI;
            this.State = this.Node.NodeState;
        }

        public void BindAttributes() {
            this.attributes.Clear();
            var atts = this.Node.Attributes;
            foreach(var att in atts.Values) {
                this.attributes.Add(new XmlAttributeViewModel {
                    LocalName = att.LocalName,
                    NamespaceURI = att.NamespaceURI,
                    Prefix = att.Prefix,
                    Value = att.Value
                });
            }
        }
        #endregion
    }
}